/**
 * @file CRhoBrentAlg.cpp Implementácia triedy CRhoBrentAlg.
 *
 * @author Peter Vagánek.
 * @date 11.4.2009.
 */

#include "CRhoBrentAlg.hpp"


bool CRhoBrentAlg::computeLogarithm(big vysledok, const bool improved) {

    tracer << "Pollard-Rho (brent):" << endl;
    if (!isInitialized()) {
        cerr << "Nie je inicializovaný kontext!" << endl;
        return false;
    }

    epoint *Z = epoint_init();
    epoint *W = epoint_init();

    epoint_copy(G, Z); // Z=P inicializacia prveho kroku
    epoint_copy(G, W); // W=P inicializacia prveho kroku

    big ai = mirvar(1);
    big aj = mirvar(1);
    big bi = mirvar(0);
    big bj = mirvar(0);

    big i = mirvar(1);
    big l = mirvar(1);

    big tmp1 = mirvar(0);
    big tmp2 = mirvar(0);

    big three = mirvar(3);

    while (true) {
        makeStep(W, ai, bi, bigBuffer[0]);
        incr(i, 1, i);

        if (epoint_comp(W, Z)) {
            if (computeIndex(ai, bi, aj, bj, vysledok)) {
                break;
            }
        }

        copy(l, tmp1);
        sftbit(tmp1, 1, tmp1); // tmp1 = 2*tmp1
        if (compare(i, tmp1) != -1) {
            epoint_copy(W, Z);
            copy(ai, aj);
            copy(bi, bj);
            sftbit(l, 1, l); // l = 2*l

            if (improved) {
                copy(l, tmp2);
                multiply(three, tmp2, tmp2);
                sftbit(tmp2, -1, tmp2); // tmp2 = tmp2 / 2
                while (compare(i, tmp2) == -1) {
                    makeStep(W, ai, bi, bigBuffer[0]);
                    incr(i, 1, i);
                }
            }
        }
    }
    mirkill(ai);
    mirkill(aj);
    mirkill(bi);
    mirkill(bj);
    mirkill(i);
    mirkill(l);
    mirkill(tmp1);
    mirkill(tmp2);
    mirkill(three);
    epoint_free(W);
    epoint_free(Z);
    return true;
}
